/*
The buffer.c file implements a circular queue as a buffer
*/

#include <types.h>

//Private Includes
#include "include/buffer.h"
#include "include/kbd_errors.h"


/* Redefine EXTERN because we'll be defining functions for real here */ 


/* Data structures */
int buffer[KBD_BUFFER_SIZE];
int head,tail,free_space;

/* Private functions prototypes */
void buffer_initialize(void);
void buffer_clear(void);
int buffer_enqueue(int n);
int buffer_dequeue(int *n);
inline int buffer_empty(void);
inline int buffer_full(void);
inline void increment(int *idx);

/* Functions implementation */

void buffer_initialize(void)
  {
    buffer_clear();
  }

void buffer_clear(void)
  {
    head=0;
    tail=0;
    free_space=KBD_BUFFER_SIZE;
  }

int buffer_enqueue(int n)
  {
    if (buffer_full())
      return E_KBD_BUFFER_FULL;

    buffer[tail]=n;
    increment(&tail);
    free_space--;

    return 0;
  }

int buffer_dequeue(int *n)
  {
    if (buffer_empty())
      return E_KBD_BUFFER_EMPTY;

    *n=buffer[head];
    increment(&head);
    free_space++;
    
    return 0;
  }

inline int buffer_empty(void)
  {
    return free_space==KBD_BUFFER_SIZE;
  }

inline int buffer_full(void)
  {
    return free_space==0;
  }

inline void increment(int *idx)
  {
    // it's like (*idx+1)&KBD_BUFFER_SIZE but faster.
    *idx=(*idx+1)&(KBD_BUFFER_SIZE-1);    
  }
